package com.innovation.ic.im.end.web.thread;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Strings;
import com.innovation.ic.b1b.framework.manager.ThreadPoolManager;
import com.innovation.ic.im.end.base.model.im_erp9.Message;
import com.innovation.ic.im.end.base.pojo.ServiceResult;
import com.innovation.ic.im.end.base.pojo.constant.MessageType;
import com.innovation.ic.im.end.base.pojo.enums.AccountIntegrationEnum;
import com.innovation.ic.im.end.base.pojo.enums.ChatPageStatusEnum;
import com.innovation.ic.im.end.base.pojo.enums.ReadStatusEnum;
import com.innovation.ic.im.end.base.service.helper.ServiceImplHelper;
import com.innovation.ic.im.end.base.service.im_erp9.ChatPairService;
import com.innovation.ic.im.end.base.thread.AbstractThread;
import com.innovation.ic.im.end.base.thread.web.SendRabbitMqMessageThread;
import com.innovation.ic.im.end.base.thread.web.SendRabbitMqReadMsgThread;
import com.innovation.ic.im.end.base.thread.web.SendScRabbitMqMessageThread;
import com.innovation.ic.im.end.base.vo.im_erp9.LoginTypeVo;
import com.innovation.ic.im.end.base.vo.im_erp9.MessageVo;
import com.innovation.ic.im.end.base.vo.im_erp9.SendMessageVo;
import com.innovation.ic.im.end.web.endpoint.Endpoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import javax.websocket.Session;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 保存Messaged对象
 */
public class SaveMessageThread extends AbstractThread implements Runnable {
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    private String urlPrefix;

    private String exchange;

    private String scReadExchange;

    private String readExchange;

    private List<Integer> loginTypeList;

    private Integer integration;

    private Map<String, Endpoint> onlineMap;

    public SaveMessageThread(Message message, Map<String, Endpoint> onlineMap, MessageVo messageVo, String exchange, List<Integer> loginTypeList, String readExchange, ThreadPoolManager threadPoolManager, Integer integration, String scReadExchange) {
        this.message = message;
        this.onlineMap = onlineMap;
        this.messageVo = messageVo;
        this.exchange = exchange;
        this.loginTypeList = loginTypeList;
        this.readExchange = readExchange;
        this.threadPoolManager = threadPoolManager;
        this.integration = integration;
        this.scReadExchange = scReadExchange;
    }

    public SaveMessageThread(Message message, Map<String, Endpoint> onlineMap, MessageVo messageVo, String urlPrefix, String exchange, List<Integer> loginTypeList, String readExchange, ThreadPoolManager threadPoolManager, Integer integration, String scReadExchange) {
        this.message = message;
        this.onlineMap = onlineMap;
        this.messageVo = messageVo;
        this.urlPrefix = urlPrefix;
        this.exchange = exchange;
        this.loginTypeList = loginTypeList;
        this.readExchange = readExchange;
        this.threadPoolManager = threadPoolManager;
        this.integration = integration;
        this.scReadExchange = scReadExchange;
    }

    public SaveMessageThread() {}

    @Override
    public void run() {
        // 更新最近联系时间
        ChatPairService chatPairService = ServiceImplHelper.getChatPairService();
        chatPairService.updateLastContactTime(message.getFromUserAccount(), message.getToUserAccount());

        logger.info("将用户【" + messageVo.getToUserAccount() + "】的消息【" + messageVo.getContent() + "】保存到消息表message中");

        // 获取用户A与用户B的聊天页面打开状态
        Integer chatPageStatus = chatPairService.getChatPageStatus(message.getToUserAccount(), message.getFromUserAccount()).getResult();
        if(chatPageStatus != null && chatPageStatus.intValue() == ChatPageStatusEnum.OPEN.getCode().intValue()){
            message.setRead(ReadStatusEnum.READ.getCode());
            message.setReadTime(new Date(System.currentTimeMillis()));
        }

        // 保存一对一消息
        ServiceResult<Integer> result = ServiceImplHelper.getMessageService().saveMessage(this.message);
        if(result != null && result.getResult() != null){
            message.setId(result.getResult());
            messageVo.setId(result.getResult());
            // 如果发送消息时，消息是已读的状态，需要推送mq消息
            if(message.getRead().intValue() == ReadStatusEnum.READ.getCode().intValue()){
                // 将本次处理成功的未读消息id通过mq推送给前端
                List<String> msgIds = new ArrayList<>();
                msgIds.add(result.getResult().toString());
                SendRabbitMqReadMsgThread sendRabbitMqReadMsgThread = new SendRabbitMqReadMsgThread(message.getFromUserAccount(), readExchange, msgIds);
                threadPoolManager.execute(sendRabbitMqReadMsgThread);
            }
        }

        // 推送websocket消息
        if(loginTypeList != null && loginTypeList.size() > 0){
            for (int i = 0; i < loginTypeList.size(); i++) {
                LoginTypeVo loginTypeVo = new LoginTypeVo(messageVo.getToUserAccount(), loginTypeList.get(i));
                String usernameStr = JSONObject.toJSON(loginTypeVo).toString();

                // 给消息接收人推送消息
                if (null != onlineMap.get(usernameStr)
                        && null != onlineMap.get(usernameStr).session) {
                    Session toSession = onlineMap.get(usernameStr).session;
                    // 将消息发送给客户端B
                    synchronized (toSession) {
                        if (toSession.isOpen()) {
                            if(messageVo.getType() != null && messageVo.getType().intValue() == MessageType.PICTURE && !Strings.isNullOrEmpty(messageVo.getFilePath())){
                                messageVo.setFilePath(urlPrefix + messageVo.getFilePath());
                            }
                            SendMessageVo sendMessageVo = new SendMessageVo();
                            BeanUtils.copyProperties(messageVo, sendMessageVo);
                            sendMessageVo.setIntegration(integration);
                            logger.info("sendMessageVo=[{}]", sendMessageVo);
                            toSession.getAsyncRemote().sendText(JSON.toJSONString(sendMessageVo));
                        }
                    }
                    logger.info("向用户【" + messageVo.getToUserAccount() + "】，发送了消息【" + messageVo.getContent() + "】");
                }
            }

            // 给自己推送一条补充了id的消息供前端展示
            for (int i = 0; i < loginTypeList.size(); i++) {
                LoginTypeVo loginTypeVo = new LoginTypeVo(messageVo.getFromUserAccount(), loginTypeList.get(i));
                String usernameStr = JSONObject.toJSON(loginTypeVo).toString();

                if(null != onlineMap.get(usernameStr) && null != onlineMap.get(usernameStr).session){
                    Session session = onlineMap.get(usernameStr).session;
                    synchronized (session) {
                        if (session.isOpen()) {
                            if(messageVo.getType() != null && messageVo.getType().intValue() == MessageType.PICTURE && !Strings.isNullOrEmpty(messageVo.getFilePath())){
                                if(!messageVo.getFilePath().contains(urlPrefix)){
                                    messageVo.setFilePath(urlPrefix + messageVo.getFilePath());
                                }
                            }
                            SendMessageVo sendMessageVo = new SendMessageVo();
                            BeanUtils.copyProperties(messageVo, sendMessageVo);
                            sendMessageVo.setIntegration(integration);
                            logger.info("sendMessageVo=[{}]", sendMessageVo);
                            session.getAsyncRemote().sendText(JSON.toJSONString(sendMessageVo));
                        }
                    }
                }
            }
        }

        // 推送rabbitMq消息更新最近联系人消息
        List<String> list = new ArrayList<>();
        list.add(message.getToUserAccount());
        list.add(message.getFromUserAccount());

        // 给erp的账号发送消息
        if(integration.intValue() == AccountIntegrationEnum.ERP_CORRELATION.getCode().intValue()){
            SendRabbitMqMessageThread sendRabbitMqMessageThread = new SendRabbitMqMessageThread(list, exchange, 1, messageVo.getFromUserAccount());
            threadPoolManager.execute(sendRabbitMqMessageThread);
        }

        // 给供应商协同账号发送消息
        if(integration.intValue() == AccountIntegrationEnum.SC_CORRELATION.getCode().intValue()){
            SendScRabbitMqMessageThread sendScRabbitMqMessageThread = new SendScRabbitMqMessageThread(list, scReadExchange, 1, messageVo.getFromUserAccount());
            threadPoolManager.execute(sendScRabbitMqMessageThread);
        }
    }
}